﻿using System.Collections.Generic;
using BuzzX8.Xmpp.StreamElements;
using BuzzX8.Xmpp.StreamElements.Builders;
using Moq;
using Moq.Protected;

namespace BuzzX8.Xmpp.Test.StreamElements.Builders
{
    public static class MockHelper
    {
        public static Mock<CompositeElementBuilder<T>> CreateCompositeBuilderMock<T>(string[] supportedElements, string[] embeddedNodes) where T : CompositeElement
        {
            Mock<CompositeElementBuilder<T>> builderMock = CreateBuilderMock<CompositeElementBuilder<T>, T>(supportedElements);
            //builderMock.Protected().Setup<ICollection<string>>("GetEmbeddedNodesNames").Returns(() => embeddedNodes);
            return builderMock;
        }

        public static Mock<StreamElementBuilder<T>> CreateBuilderMock<T>(params string[] supportedElements) where T : StreamElement
        {
            return CreateBuilderMock<StreamElementBuilder<T>, T>(supportedElements);
        }

        public static Mock<TBuilder> CreateBuilderMock<TBuilder, TElement>(params string[] supportedElements) where TBuilder : StreamElementBuilder<TElement> 
                                                                                                              where TElement : StreamElement
        {
            Mock<TBuilder> builderMock = CreateBuilderMock<TBuilder, TElement>();
            builderMock.Protected()
                       .Setup<IEnumerable<string>>("GetSupportedElementNames")
                       .Returns(() => supportedElements);
            return builderMock;
        }

        public static Mock<TBuilder> CreateBuilderMock<TBuilder, TElement>() where TBuilder : StreamElementBuilder<TElement> 
                                                                             where TElement : StreamElement
        {
            Mock<TBuilder> builderMock = new Mock<TBuilder>();
            builderMock.CallBase = true;
            return builderMock;
        }

        public static void SetRootElement<TBuilder, TElement>(this Mock<TBuilder> builderMock, string elementName, params object[] constructorParams) where TBuilder : StreamElementBuilder<TElement>
                                                                                                                                          where TElement : StreamElement
        {
            Mock<TElement> elementMock = new Mock<TElement>(constructorParams);
            builderMock.Protected().Setup<TElement>("CreateNewElement", elementName)
                                   .Returns(() => elementMock.Object);
        }
    }
}
